import { Injectable, Logger } from '@nestjs/common';
import { PrismaService } from '../prisma/prisma.service';
import { Prisma, Exam } from '@prisma/client';

@Injectable()
export class ExamService {
  private readonly logger = new Logger(ExamService.name);

  // 提交考试答案并计算分数
  async submitExam(examId: number, userId: number, answers: { questionId: number; answer: string }[]): Promise<{ score: number }> {
    this.logger.log(`用户 ${userId} 提交考试 ${examId} 的答案`);

    // 使用事务确保数据一致性
    return await this.prisma.$transaction(async (prisma) => {
      const exam = await prisma.exam.findUnique({
        where: { id: examId },
        include: { questions: true }
      });

      if (!exam) {
        throw new Error('考试不存在');
      }

      // 验证考试时间
      const now = new Date();
      if (now < new Date(exam.startTime)) {
        throw new Error('考试还未开始');
      }
      if (now > new Date(exam.endTime)) {
        throw new Error('考试已结束');
      }

      // 检查是否已提交过考试
      const existingResult = await prisma.examResult.findFirst({
        where: {
          examId,
          userId
        }
      });

      if (existingResult) {
        throw new Error('已经提交过此考试');
      }

      // 计算得分
      let totalScore = 0;
      const questionScores = new Map(exam.questions.map(q => [q.id, q.score || 0]));
      const answerResults = [];

      for (const answer of answers) {
        const question = exam.questions.find(q => q.id === answer.questionId);
        if (!question) {
          throw new Error(`题目 ${answer.questionId} 不存在`);
        }

        const isCorrect = question.answer === answer.answer;
        const score = isCorrect ? (question.score || 0) : 0;
        totalScore += score;

        answerResults.push({
          content: answer.answer,
          isCorrect,
          score,
          questionId: question.id
        });
      }

      // 保存考试结果
      const examResult = await prisma.examResult.create({
        data: {
          exam: { connect: { id: examId } },
          user: { connect: { id: userId } },
          score: totalScore,
          submittedAt: now,
          answers: {
            create: answerResults
          }
        },
        include: {
          answers: true
        }
      });

      this.logger.log(`用户 ${userId} 完成考试 ${examId}，得分: ${totalScore}`);
      return { score: totalScore };
    });
  }

  constructor(private prisma: PrismaService) {}

  async exam(examWhereUniqueInput: Prisma.ExamWhereUniqueInput): Promise<Exam | null> {
    return this.prisma.exam.findUnique({
      where: examWhereUniqueInput,
      include: {
        questions: true,
        createdBy: true
      }
    });
  }

  async exams(params: {
    skip?: number;
    take?: number;
    cursor?: Prisma.ExamWhereUniqueInput;
    where?: Prisma.ExamWhereInput;
    orderBy?: Prisma.ExamOrderByWithRelationInput;
  }): Promise<Exam[]> {
    const { skip, take, cursor, where, orderBy } = params;
    const now = new Date();
    
    // 添加时间过滤条件，只返回未结束的考试
    const timeFilter = {
      endTime: {
        gte: now
      }
    };

    return this.prisma.exam.findMany({
      skip,
      take,
      cursor,
      where: {
        ...where,
        ...timeFilter
      },
      orderBy,
      include: {
        questions: true,
        createdBy: true
      }
    });
  }

  async getAvailableExamsWithStatus(userId: number): Promise<any[]> {
    const now = new Date();
    const exams = await this.prisma.exam.findMany({
      where: {
        startTime: { lte: now },
        endTime: { gte: now }
      },
      include: {
        questions: true,
        createdBy: true
      }
    });

    // 获取用户已完成的考试
    const completedExams = await this.prisma.examResult.findMany({
      where: {
        userId: userId
      },
      select: {
        examId: true,
        score: true
      }
    });

    // 将考试完成状态添加到考试信息中
    return exams.map(exam => {
      const completedExam = completedExams.find(ce => ce.examId === exam.id);
      return {
        ...exam,
        completed: !!completedExam,
        score: completedExam?.score
      };
    });

  }

  async createExam(data: Prisma.ExamCreateInput): Promise<Exam> {
    this.logger.log(`开始创建新考试: ${JSON.stringify(data)}`);
    try {
      const { questions, ...examData } = data as any;
      this.logger.log(`questions: ${JSON.stringify(questions)}`);
      // 使用事务确保考试创建和题目关联的原子性
      const exam = await this.prisma.$transaction(async (prisma) => {
        // 创建考试
        this.logger.log('创建考试记录...');
        const createdExam = await prisma.exam.create({
          data: {
            ...examData
          },
          include: {
            questions: true,
            createdBy: true
          }
        });
        this.logger.log(`考试创建成功，ID: ${createdExam.id}`);
        
        if (questions && Array.isArray(questions.connect) && questions.connect.length > 0) {
          // 更新题目的examId
          await prisma.question.updateMany({
            where: {
              id: {
                in: questions.connect.map(q => q.id)
              }
            },
            data: {
              examId: createdExam.id
            }
          });
          this.logger.log(`已关联 ${questions.connect.length} 道题目到考试`);
        }

        // 重新获取包含更新后题目的考试信息
        return prisma.exam.findUnique({
          where: { id: createdExam.id },
          include: {
            questions: true,
            createdBy: true
          }
        });
      });

      this.logger.log(`考试创建流程完成，返回考试信息`);
      return exam;
    } catch (error) {
      this.logger.error(`创建考试失败: ${error.message}`);
      this.logger.error(`错误详情: ${JSON.stringify(error)}`);
      throw error;
    }
  }

  async updateExam(params: {
    where: Prisma.ExamWhereUniqueInput;
    data: Prisma.ExamUpdateInput;
  }): Promise<Exam> {
    const { where, data } = params;
    this.logger.log(`开始更新考试 ID: ${where.id}`);
    try {
      const { questions, ...examData } = data as any;
      this.logger.log(`更新数据: ${JSON.stringify(examData)}`);
      this.logger.log(`题目数据: ${JSON.stringify(questions)}`);
  
      const exam = await this.prisma.$transaction(async (prisma) => {
        // 先断开所有现有题目的关联
        await prisma.question.updateMany({
          where: { examId: where.id },
          data: { examId: null }
        });
        this.logger.log('已断开现有题目关联');
  
        // 更新考试基本信息和题目关联
        this.logger.log('更新考试基本信息和题目关联...');
        const updatedExam = await prisma.exam.update({
          where,
          data: {
            ...examData,
            questions: Array.isArray(questions) ? {
              connect: questions.map(q => ({ id: q.id }))
            } : undefined
          },
          include: {
            questions: true,
            createdBy: true
          }
        });
        this.logger.log(`考试更新成功，ID: ${updatedExam.id}`);
        
        if (questions && Array.isArray(questions)) {
          this.logger.log(`已关联 ${questions.length} 道题目到考试`);
        }
  
        // 重新获取包含更新后题目的考试信息
        return prisma.exam.findUnique({
          where: { id: updatedExam.id },
          include: {
            questions: true,
            createdBy: true
          }
        });
      });
  
      this.logger.log(`考试更新流程完成，返回更新后的考试信息`);
      return exam;
    } catch (error) {
      this.logger.error(`更新考试失败: ${error.message}`);
      this.logger.error(`错误详情: ${JSON.stringify(error)}`);
      throw error;
    }
  }

  async deleteExam(where: Prisma.ExamWhereUniqueInput): Promise<Exam> {
    this.logger.log(`删除考试 ID: ${where.id}`);
    return this.prisma.exam.delete({
      where,
      include: {
        questions: true,
        createdBy: true
      }
    });
  }

  async getExamStatus(examId: number): Promise<'NOT_STARTED' | 'IN_PROGRESS' | 'ENDED'> {
    const exam = await this.exam({ id: examId });
    if (!exam) {
      throw new Error('考试不存在');
    }

    const now = new Date();
    if (now < exam.startTime) {
      return 'NOT_STARTED';
    } else if (now > exam.endTime) {
      return 'ENDED';
    } else {
      return 'IN_PROGRESS';
    }
  }

  async generateRandomQuestions(params: {
    examId: number;
    count: number;
    subject: string;
  }): Promise<Exam> {
    const { examId, count, subject } = params;
    this.logger.log(`为考试 ${examId} 随机生成 ${count} 道 ${subject} 题目`);

    // 获取指定科目的所有可用题目
    const availableQuestions = await this.prisma.question.findMany({
      where: {
        subject,
        examId: null,  // 未分配到考试的题目
      },
    });

    if (availableQuestions.length < count) {
      throw new Error(`可用题目数量不足，当前只有 ${availableQuestions.length} 道题目`);
    }

    // 随机选择指定数量的题目
    const selectedQuestions = availableQuestions
      .sort(() => Math.random() - 0.5)
      .slice(0, count);

    // 更新考试，添加选中的题目
    return this.prisma.exam.update({
      where: { id: examId },
      data: {
        questions: {
          connect: selectedQuestions.map(q => ({ id: q.id })),
        },
      },
      include: {
        questions: true,
        createdBy: true,
      },
    });
  }

  async checkExamAccess(examId: number, userId: number): Promise<boolean> {
    const exam = await this.exam({ id: examId });
    if (!exam) {
      throw new Error('考试不存在');
    }

    // 检查是否是考试创建者
    if (exam.userId === userId) {
      return true;
    }

    // 检查考试时间
    const status = await this.getExamStatus(examId);
    if (status !== 'IN_PROGRESS') {
      return false;
    }

    // 检查是否已参加过考试
    const existingResult = await this.prisma.examResult.findFirst({
      where: {
        examId,
        userId,
      },
    });

    return !existingResult; // 如果没有考试记录，则允许访问
  }

  async getExamStatistics(examId: number): Promise<{
    scoreDistribution: { score: number; count: number }[];
    passRate: number;
    averageScore: number;
    totalStudents: number;
    highestScore: number;
    lowestScore: number;
  }> {
    this.logger.log(`获取考试 ${examId} 的统计数据`);

    const exam = await this.exam({ id: examId });
    if (!exam) {
      throw new Error('考试不存在');
    }

    // 获取所有考试结果
    const examResults = await this.prisma.examResult.findMany({
      where: { examId },
      select: { score: true }
    });

    if (examResults.length === 0) {
      throw new Error('暂无考试数据');
    }

    // 计算基础统计数据
    const scores = examResults.map(result => result.score);
    const totalStudents = scores.length;
    const totalScore = scores.reduce((sum, score) => sum + score, 0);
    const averageScore = totalScore / totalStudents;
    const highestScore = Math.max(...scores);
    const lowestScore = Math.min(...scores);

    // 计算及格率（默认60分及格）
    const passCount = scores.filter(score => score >= 60).length;
    const passRate = (passCount / totalStudents) * 100;

    // 计算成绩分布
    const distribution = new Map<number, number>();
    const ranges = [0, 60, 70, 80, 90, 100];
    
    for (let i = 0; i < ranges.length - 1; i++) {
      const min = ranges[i];
      const max = ranges[i + 1];
      const count = scores.filter(score => score >= min && score < max).length;
      distribution.set(min, count);
    }

    // 转换成绩分布为数组格式
    const scoreDistribution = Array.from(distribution).map(([score, count]) => ({
      score,
      count
    }));

    return {
      scoreDistribution,
      passRate,
      averageScore,
      totalStudents,
      highestScore,
      lowestScore
    };
  }

  async getStudentResults(userId: number) {
    this.logger.log(`获取学生 ${userId} 的考试结果`);
    try {
      const results = await this.prisma.examResult.findMany({
        where: {
          userId: userId
        },
        include: {
          exam: {
            select: {
              title: true,
              subject: true,
              totalScore: true,
              passingScore: true
            }
          }
        },
        orderBy: {
          submittedAt: 'desc'
        }
      });

      return results.map(result => ({
        id: result.examId,
        title: result.exam.title,
        subject: result.exam.subject,
        score: result.score,
        totalScore: result.exam.totalScore,
        passingScore: result.exam.passingScore,
        completedAt: result.submittedAt,
        passed: result.score >= result.exam.passingScore
      }));
    } catch (error) {
      this.logger.error(`获取学生考试结果失败: ${error.message}`);
      throw new Error('获取考试结果失败');
    }
  }

}